import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { Card, message, Form, Input, Modal, Checkbox, Button, Upload, Select, Radio } from 'antd';
import { FormInstance } from 'antd/lib/form';
import { UploadOutlined, FolderOpenOutlined, SaveOutlined, DownloadOutlined } from '@ant-design/icons';
import { Graph, Model, Node, Edge, Shape } from '@antv/x6'
import JSZip from 'jszip';
import * as xmind from 'xmind';
import Hierarchy from '@antv/hierarchy';
import TreeView from '../treeView';

interface HierarchyResult {
  id: any
  x: number
  y: number
  data: {
    faultCode: string
    faultDescription: string
  }
  children: HierarchyResult[]
}
const mapStateToProps = (state: any) => ({
  knowledgeApproval: state.knowledgeApproval,
});
class ApplyModal extends PureComponent<any, any> {
  constructor(props: any) {
    super(props);
    this.state = {
      userId: '', //  用户id
      type: '1',  //  当前树/完整树
      screenFit: '1',
      // currentSpecialty: '', //  当前所选专业
      currentData: [],  //  当前申请故障数据
      currentIds: {}, //  当前申请故障数据关系
      currentTargetModel: [],

      sourceData: [], //  当前专业tree数据
      fullData: [], //  完整树数据
      fullIds: {},  //  完整树数据节点关系
      fullTargetModel: [],
    }
  }

  componentDidMount() {
    const { dispatch } = this.props;
    this.props.onRef(this);
  }

  componentDidUpdate(prevProps: any) {
    const { modalVisible, record, dispatch} = this.props
    if (modalVisible && modalVisible !== prevProps.modalVisible) {
      //  获取本次提交tree数据，以及获取根节点描述
      this.queryApplyRecordData({
        id: record.applyRecordId,
      }).then((res1: any) => {
        if (res1.statusCode == '0') {
          const tempDesp = res1?.data?.faultTree[0]?.faultDescription;
          //  获取知识库rootId
          this.queryFullTreeData({
            majorCode: record.majorCode,
            faultDescription: tempDesp,
            pageNo: 1,
            pageSize: 999
          }).then((res2: any) => {
            // console.log(res2);
            if (res2.statusCode == '0') {
              const tempRootId = res2?.data?.list[0]?.rootId || -1;
              this.queryFullTreeData({
                majorCode: record.majorCode,
                rootId: tempRootId,
                pageNo: 1,
                pageSize: 9999,
              }).then((res3: any) => {
                console.log(res3);
                if (res3.statusCode == '0') {
                  //  当前提交数据
                  const currentTree = this.formatCurrentData(res1?.data?.faultTree || []);
                  //  关系
                  const ids = this.getFulltreeIds(currentTree);
                  //  坐标
                  const currentDataModel = this.getCoordinates(currentTree[0]);
                  const currentTargetModel = this.transformModel(currentDataModel, ids);
        
                  //  完整tree
                  const sourceData = this.formatSourceTreeData(res3?.data?.list);
                  const sourceDataList = this.treeToArray1(sourceData, '');
                  const fullData = this.combineTreeData(currentTree, sourceDataList);
                  const fullDataIds = this.getFulltreeIds(fullData);
                  //  计算坐标
                  const fullDataModel = this.getCoordinates(fullData[0]);
                  //  整理tree视图数据
                  const fullTargetModel = this.transformModel(fullDataModel, fullDataIds);
                  this.setState({
                    currentData: currentTree,
                    currentIds: ids,
                    currentTargetModel: currentTargetModel,
                    sourceData: sourceDataList, //  完整tree数据
                    fullData: fullData,
                    fullIds: fullDataIds,
                    fullTargetModel: fullTargetModel,
                  }, () => {
                    this.treeViewRef.setData(currentTargetModel, ids);
                  })
                }
              })
            }
          })
        }
      })


      /* Promise.all([
        dispatch({
          type: 'http/getDataWithRes',
          payload: { 
            url: '/mscontent/knowledge/apply/record/findApplyRecord',
            id: record.applyRecordId,
          },
          callback: (res: any) => {},  // 获取当前tree
        }),
        dispatch({
          type: 'http/getDataWithRes',
          payload: { 
            url: '/mscontent/knowledge/fault/list',
            majorCode: record.majorCode,
            rootId: record.rootId,
            pageNo: 1,
            pageSize: 9999,
          },
          callback: (res: any) => {}, //  获取完整tree
        })
      ]).then((res: any) => {
        //  当前提交数据
        const currentTree = this.formatCurrentData(res[0]?.data?.faultTree || []);
        //  关系
        const ids = this.getFulltreeIds(currentTree);
        //  坐标
        const currentDataModel = this.getCoordinates(currentTree[0]);
        const currentTargetModel = this.transformModel(currentDataModel, ids);

        //  完整tree
        const sourceData = this.formatSourceTreeData(res[1]?.data?.list);
        //  使用 faultCode 构建父子级关系
        const sourceDataList = this.treeToArray1(sourceData, '');
        const fullData = this.combineTreeData(currentTree, sourceDataList);
        const fullDataIds = this.getFulltreeIds(fullData);
        //  计算坐标
        const fullDataModel = this.getCoordinates(fullData[0]);
        //  整理tree视图数据
        const fullTargetModel = this.transformModel(fullDataModel, fullDataIds);
        this.setState({
          currentData: currentTree,
          currentIds: ids,
          currentTargetModel: currentTargetModel,
          sourceData: sourceDataList, //  完整tree数据
          fullData: fullData,
          fullIds: fullDataIds,
          fullTargetModel: fullTargetModel,
        }, () => {
          this.treeViewRef.setData(currentTargetModel, ids);
        })
      }) */
    }
  }

  //  获取本次提交知识库
  queryApplyRecordData = (params: {}) => {
    const { dispatch } = this.props;
    return dispatch({
      type: 'http/getDataWithRes',
      payload: { 
        url: '/mscontent/knowledge/apply/record/findApplyRecord',
        ...params,
      },
      callback: (res: any) => {
        // 获取当前tree
      }
    })
  }

  //  获取完整知识库
  queryFullTreeData = (params: {}) => {
    const { dispatch } = this.props;
    return dispatch({
      type: 'http/getDataWithRes',
      payload: { 
        url: '/mscontent/knowledge/fault/list',
        ...params,
      },
      callback: (res: any) => {
        // 获取当前tree
      }
    })
  }

  //  整理当前数据（使用 faultCode 作id）
  formatCurrentData = (list: any[]) => {
    const tempList = JSON.parse(JSON.stringify(list));
    function formatData(tree: any[]) {
      for (let item of tree) {
        const tempChildren = item?.children || [];
        // const texts = item.title.split('-');
        item.id = item.faultCode || '';
        if (tempChildren.length > 0) {
          formatData(item.children);
        }
      }
    }
    formatData(tempList);
    return tempList
  }

  //  处理接口返回完整知识库 list 数据
  formatSourceTreeData = (list: []) => {
    return this.arrayToTree1(list, 'parentId');
  }

  arrayToTree1 = (items: any, pKey: string) => {
    let res = []; // 存放结果集
    let map = {};
    // 判断对象是否有某个属性
    let getHasOwnProperty = (obj: any, property: any) => Object.prototype.hasOwnProperty.call(obj, property);
    // 边做map存储，边找对应关系
    for (const i of items) {
      map[i.id] = {
        ...i,
        // title: i.faultCode + '-' + i.faultDescription,
        children: getHasOwnProperty(map, i.id)
          ? map[i.id].children
          : [],
      };
      const newItem = map[i.id];
      if (!i[pKey]) {
        //  根节点，无父级
        res.push(newItem);
      } else {
        if (!getHasOwnProperty(map, i[pKey])) {
          map[i[pKey]] = {
            children: [],
          };
        }
        map[i[pKey]].children.push(newItem);
      }
    }
    return res;
  }

  //  添加 parrentCode（使用 faultCode 构建关系）
  treeToArray1 = (tree: any, pcode: string) => {
    let res: any[] = [];
    for (const item of tree) {
      const {
        children,
        faultCode,
        faultDescription,
        ...i
      } = item;
      if (children && children.length > 0) {
        const temp = this.treeToArray1(children, faultCode);
        res = res.concat(temp);
      }
      res.push({
        faultCode,
        faultDescription,
        parrentCode: pcode,
        ...i
      });
    }
    return res;
  }

  //  整理完整tree数据
  formatSourceData = (list: []) => {
    let res: any[] = []
    list && list.forEach(item => {
      const { faultCode, faultDescription, parentId, id } = item
      res.push({
        faultCode,
        faultDescription,
        id,
        parrentCode: parentId || '',
        title: faultCode + '-' + faultDescription,
      })
    })
    return res;
  }
  
  //  获取树节点关系
  getFulltreeIds = (data: any[]) => {
    const ids = {};
    function formatData(tree: any[]) {
      for (let item of tree) {
        const { children } = item
        ids[item.faultCode] = [];
        if (children.length > 0) {
          ids[item.faultCode] = children.map(t => t.faultCode);
          formatData(children)
        }
      }
    }
    if (data[0]) {
      const topicChildren = data[0]?.children || [];
      ids[data[0].faultCode] = topicChildren.map(t => t.faultCode);
      topicChildren && formatData(data[0]?.children);
    }
    return ids;
  }

  //  合并
  combineTreeData = (currentData: any, sourceData: any[]) => {
    const tempCurrent = JSON.parse(JSON.stringify(currentData));
    const tempSource = JSON.parse(JSON.stringify(sourceData));
    let tempFullData: any[] = [];
    const res1 = this.treeToArray(tempCurrent, '');
    let res = {};
    tempSource.forEach((item: any) => {
      res[item.faultCode] = {
        ...item,
      };
    });
    res1.forEach((item) => {
      res[item.faultCode] = {
        ...item,
      };
    });
    tempFullData = this.arrayToTree(Object.values(res));
    return tempFullData;
  }

  //  tree 转 array
  treeToArray = (tree: any, pcode: string) => {
    let res: any[] = [];
    for (const item of tree) {
      const {
        children,
        faultCode,
        faultDescription,
        attributedTitle,
        ...i
      } = item;
      if (children && children.length > 0) {
        const temp = this.treeToArray(children, faultCode);
        res = res.concat(temp);
      }
      res.push({
        faultCode,
        faultDescription,
        parrentCode: pcode,
        ...i,
      });
    }
    return res;
  }

  //  array -> tree
  arrayToTree = (items: any) => {
    let res = []; // 存放结果集
    let map = {};
    // 判断对象是否有某个属性
    let getHasOwnProperty = (obj: any, property: any) => Object.prototype.hasOwnProperty.call(obj, property);
    // 边做map存储，边找对应关系
    for (const i of items) {
      map[i.faultCode] = {
        ...i,
        children: getHasOwnProperty(map, i.faultCode)
          ? map[i.faultCode].children
          : [],
      };
      const newItem = map[i.faultCode];
      if (i.parrentCode === "") {
        res.push(newItem);
      } else {
        if (!getHasOwnProperty(map, i.parrentCode)) {
          map[i.parrentCode] = {
            children: [],
          };
        }
        map[i.parrentCode].children.push(newItem);
      }
    }
    return res;
  }

  //  计算坐标
  getCoordinates = (data: any) => {
    const result = Hierarchy.mindmap(data, {
      direction: 'H',
      getHeight() {
        return 120
      },
      getWidth() {
        return 100
      },
      getHGap() {
        return 200
      },
      getVGap() {
        return 1
      },
      getSide: () => {
        return 'right'
      },
    })
    const model: Model.FromJSONData = { nodes: [], edges: [] };
    const traverse = (data: HierarchyResult) => {
      if (data) {
        model.nodes?.push({
          id: `${data.data.faultCode}`,
          x: data.x + 250,
          y: data.y + 250,
          code: data.data.faultCode,
          desp: data.data.faultDescription,
          // title: data.data.faultDescription,
          shape: 'circle',
          width: 260,
          height: 88,
          attrs: {
            body: {
              fill: '#5F95FF',
              stroke: 'transparent',
              rx: 10,
              ry: 10,
            },
          },
        })
      }
      if (data.children) {
        data.children.forEach((item: HierarchyResult) => {
          model.edges?.push({
            source: `${data.data.faultCode}`, //  data.id
            target: `${item.data.faultCode}`, //  data.id
            attrs: {
              line: {
                stroke: '#A2B1C3',
                strokeWidth: 1,
                targetMarker: null,
              },
            },
          })
          traverse(item)
        })
      }
    }
    traverse(result);
    return model;
  }

  //  转换数据
  transformModel = (model: any, ids: any) => {
    let data = JSON.parse(JSON.stringify(model));
    const { nodes, edges } = data
    let targetModel: any = { nodes: [], edges: edges };
    nodes.forEach((n: any, idx: number) => {
      // console.log(n.id);
      let tempInfo = {
        code: '',
        text: n.desp
      };
      if (idx !== 0) {
        //  起始
        tempInfo.code = n.code;
      }
      let tempN = {
        id: n.id,
        shape: 'tree-node',
        width: 260,
        height: 88,
        leaf: !(ids[n.id] && ids[n.id].length > 0),
        leafLen: ids[n.id] ? ids[n.id].length : 0,
        x: n.x,
        y: n.y,
        attrs: {
          code: {
            textWrap: {
              text: tempInfo.code
            }
          },
          label: {
            textWrap: {
              text: tempInfo.text
            }
          },
        }
      }
      targetModel.nodes.push(tempN);
    })
    return targetModel;
  }

  //  取消操作
  cancel = () => {
    const { closeModal } = this.props;
    closeModal();
    this.setState({
      type: '1',
      screenFit: '1',
      currentData: [],
      currentIds: {},
      currentTargetModel: [],
      sourceData: [],
      fullData: [],
      fullIds: {},
      fullTargetModel: [],
    })
    this.treeViewRef && this.treeViewRef.clearGraph();
  }

  //  下载
  downloadKownledgeTree = () => {
    const { currentData, currentIds, currentTargetModel } = this.state;
    // const {Workbook, Topic, Dumper} = window;
    const {Workbook, Topic, Dumper, Marker} = xmind

    if (!(currentData && currentData.length > 0)) return;
    const topicTitle = currentData[0].faultDescription;
    const workbook = new Workbook();
    const topic = new Topic({sheet: workbook.createSheet('topic', topicTitle)});

    function loopCreate(tree: any[]) {
      for (let item of tree) {
        const { children, faultCode, faultDescription } = item;
        // const tempTitle = faultCode + '-' + faultDescription;
        if (children.length > 0) {
          let tempCid = '';
          if (!faultCode || faultCode === 'topic') {
            tempCid = faultDescription
          } else {
            tempCid = faultCode + '-' + faultDescription;
          }
          children.forEach((c: any) => {
            const { faultCode = '', faultDescription = '' } = c;
            topic
              .on(topic.cid(tempCid))
              .add({title: faultCode + '-' + faultDescription})
          })
          loopCreate(children);
        }
      }
    }
    loopCreate(currentData);
    const dumper = new Dumper({workbook});
    const files = dumper.dumping();
    const jszip = new JSZip();
    for (const file of files) {
      // console.log(file.filename, '\n', file.value);
      jszip.file(file.filename, file.value);
    }
    jszip.generateAsync({ type:'blob' }).then((content) => {
      const link = document.createElement('a');
      link.href = URL.createObjectURL(content);
      link.download = `${topicTitle}.xmind`;
      link.click();
      link.remove();
    });
  }

  //  切换当前树/完整树
  onChangeType = (val: any) => {
    const { type, currentTargetModel, currentIds, fullIds, fullTargetModel } = this.state;
    if (type == val) return; 
    this.setState({
      type: val,
    }, () => {
      if (val == 1) {
        if (currentTargetModel.nodes && currentTargetModel.nodes.length > 0) {
          this.treeViewRef.setData(currentTargetModel, currentIds);
        } else {
          this.treeViewRef.clearGraph();
        }
      } else if (val == 2) {
        if (fullTargetModel.nodes && fullTargetModel.nodes.length > 0) {
          this.treeViewRef.setData(fullTargetModel, fullIds);
        } else {
          this.treeViewRef.clearGraph();
        }
      }
    })
  }

  //  画笔比列
  handleGraphFit = (val: any) => {
    this.setState({
      screenFit: val,
    })
    if (this.treeViewRef) {
      const { graph } = this.treeViewRef.state;
      if (val === '1' ) {
        //  适应画布
        graph && graph.zoomToFit({ padding: 24 });
      } else if (val === '2') {
        //  100%
        graph && graph.zoomTo(1);
      }
    }
  }

  render() {
    const { modalVisible, specialtyData } = this.props;
    const { type, screenFit } = this.state;
    return (
      <>
        <Modal
          style={{ top: 20 }}
          footer={null}
          title="知识库"
          width={1200}
          bodyStyle={{ maxHeight: '800px' }}
          visible={modalVisible}
          onCancel={this.cancel}
        >
          <div style={{ width: '100%', marginBottom: '15px' }}>
            <div style={{ marginBottom: '16px', position: 'relative' }}>
              <Button onClick={() => this.downloadKownledgeTree()} icon={<DownloadOutlined />}>下载</Button>
              <span style={
                { 
                  position: 'absolute', 
                  left: '50%', 
                  top: '6px',
                  transform: 'translateX(-50%)',
                  fontWeight: 600,
                }
              }>{ specialtyData.label }</span>
            </div>
            <div>
              <Radio.Group 
                onChange={({target: { value }}) => {
                  this.onChangeType(value)
                }}
                value={type}
                optionType="button"
                buttonStyle="solid"
              >
                <Radio.Button value="1">本次维护内容</Radio.Button>
                <Radio.Button value="2">完整故障树预览</Radio.Button>
              </Radio.Group>
            </div>
            <TreeView
              onRef={(modalRef: any) => (this.treeViewRef = modalRef)}
              clickNode={(n: any) => {}}
              styels={{
                width: '100%',
                height: '655px'
              }}
            />
          </div>
          <div style={{ position: 'absolute', right: '65px', bottom: '80px', }}>
            {/* 适应画布、100% */}
            <Select
              style={{
                width: '100px',
              }}
              value={screenFit}
              placeholder="缩放比列"
              onSelect={(v: any) => {
                this.handleGraphFit(v);
              }}
              options={[
                {
                  value: '1',
                  label: '适应画布',
                },
                {
                  value: '2',
                  label: '100%',
                },
              ]}
            />
          </div>
        </Modal>
      </>
    )
  }
}
export default connect(mapStateToProps)(ApplyModal);
